home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / eulisp / mpfeel.lha / MPFeel / Plurals / mp_mem_mgmt.m < prev    next >
Text File  |  1992-07-05  |  22KB  |  724 lines

  1. /*
  2.  *    Plurals
  3.  *
  4.  *    Author:    S.C.Merrall
  5.  *
  6.  *    File:      mp_mem_mgmt.m
  7.  *
  8.  *    Contents:        alloc_plural
  9.  *            mp_free_plurals        visible
  10.  *            extend_plural_space
  11.  *            find_space
  12.  *                      init_mem
  13.  *
  14.  *    Description:        These functions manage the PE's local memory
  15.  *            that is the plural-space and the 
  16.  *            heap space keeping the free information updated. 
  17.  *            They create functions with handles specifiued in 
  18.  *            mp_plurals.h and mp_plurals.c
  19.  *
  20.  *    Change History:
  21.  *
  22.  *    Date   Name Comment
  23.  *  -------- ---- -------
  24.  *  29:01:91 SCM  Created
  25.  *  13:02:91 SCM  Sussed the abstraction
  26.  *  19:02:91 SCM  Changed to come in line with renamed object system
  27.  *  15:04:91 SCM  Changed to allow heap allocation in 32-bit blocks
  28.  *  16:06:91 SCM  Moved definition of scratch to mp_io.m
  29.  *  21:05:91 SCM  alloc_plural no longer visible, wrapped by make_plural
  30.  *  20:01:92 SCM  Modified to use paired processors
  31.  *  26:03:92 SCM  free_plural axed.
  32.  *  26:03:92 SCM  mp_free_plurals, called by fe_gc, updates entire plural space
  33.  *  27:03:92 SCM  memory management information now in reverse "sense"
  34.  *  08:04:92 SCM  plural_space visible to front end for temp plural space!
  35.  *  10:04:92 SCM  Implementing a fe driven stack system for GC protect.
  36.  *  27:05:92 SCM  Began converting to rectangular allocator.
  37.  *
  38.  */
  39.  
  40. /*    To be consistent with Eulisp the plural structure will not
  41.  *    contain LispObjects but will contain a pointer to a LispObject
  42.  *    which will be allocated from the heap space on the PE. 
  43.  *       The plural space will be allocated from the low end of the
  44.  *    local memory and the heap space from the high end. This scheme
  45.  *    has the advantage that the objects in the plural space are all
  46.  *    the same size.
  47.  *       At this stage I am assuming that each elements of a
  48.  *    plural's LispObject will be on the same PE's local memory.
  49.  *    Since we have only 16K of local memory this gives us a high
  50.  *    bit we can hopefully use to indicate free memory. 
  51.  */
  52.  
  53. /* Include Files */
  54. /* ======= ===== */
  55.  
  56. #include <mpl.h>
  57. #include "proc_pair.h"
  58. #include "seq_net.h"
  59. #include <stdio.h>
  60.  
  61. #include "mp_eubang.h"
  62.  
  63. /*  #include "constant.h" inside mp_eubang.h, which is now included because
  64.  *  we have a visible function
  65.  */
  66.  
  67. #include "mp_object.h"
  68. #include "mp_debug_off.h"
  69. #include "mp_mem_mgmt.h"
  70. #include "mp_gc.h"
  71.  
  72. /* External Variables */
  73. /* ======== ========= */
  74.  
  75. extern object MPC_chain;  /*  This variable only used in this file so there 
  76.                *  doesn't seem to be too much point in putting
  77.                *  it in a header
  78.                */
  79.  
  80. /* Global Variables */
  81. /* ====== ========= */
  82.  
  83. plural heap_header  heap_memory[MEMORY_SIZE];   /*  Reserve MEMORY_SIZE 32-bit
  84.                                                  *  words of memory
  85.                                                  */
  86.  
  87. /* plural natural plural_memory[] = (plural natural *plural) &heap_memory[0]; */
  88.  
  89. plural natural *plural plural_memory;
  90.  
  91.                                           /*  Plural space is allocated 
  92.                        *  in 16-bit blocks
  93.                        */
  94.  
  95. visible natural plural_space = TOP;       /*  Top of plural space. This is
  96.                                            *  always the same on all PEs
  97.                                            *  hence a singular value. 
  98.                                            */
  99.  
  100. visible plural natural  heap_space=0;     /*  Bottom of heap space. Varies
  101.                                            *  between PE's so a plural
  102.                                            *  value. 
  103.                        */
  104.  
  105. visible natural stack_base = TOP;      /*  For the purposes of GC protection
  106.                        *  we need to be able to stack all 
  107.                        *  the active things we are holding
  108.                        *  in mid operation. We use the
  109.                        *  plural space as this stack and
  110.                        *  modify the collector and
  111.                        *  and allocator.
  112.                        */
  113.  
  114. /*----------------------------------------------------------------------------*
  115.  * Function   : extend_plural_space
  116.  *
  117.  * Parameters : none
  118.  *
  119.  * Description: Extends the plural space by one slot initialising the 
  120.  *        space management data at the same time. The slot on
  121.  *        each PE is marked as free, having its high bit set, the
  122.  *        remaining bits indicating how taller column of free PEs
  123.  *        (for that slot) it is at the bottom of.
  124.  *
  125.  * Result     : natural:    FAIL    - heap space and plural space clashed
  126.  *                SUCCESS - plural space successfully extended
  127.  *---------------------------------------------------------------------------*/
  128.  
  129. #ifdef __STDC__
  130.  
  131. natural extend_plural_space( void ) 
  132.  
  133. #else
  134.  
  135. natural extend_plural_space( )
  136.  
  137. #endif
  138.  
  139. {
  140.   int aok = TRUE;
  141. DBG_CALL("extend_plural_space");
  142. DBG_ARGS(fprintf(dbg,"void"));
  143.  
  144.   /*  On entry the active set should be "all"
  145.    *  If any of the PE's plural and heap spaces are about to clash we 
  146.    *  cannot extend. */
  147.   
  148.   PP_on_set() {
  149.     
  150.     if (!space_to_grow(sizeof(natural))) {
  151.  
  152.       fprintf(stderr,"extend_plural_space:No Space, trying back end GC\n");
  153.       mp_gc();
  154.     }
  155.     
  156.     if (!space_to_grow(sizeof(natural))) {
  157.  
  158. DBG_FAIL(fprintf(dbg,"FAIL: Still No Space after mp-gc"));
  159.       aok = FALSE;
  160.     }
  161.     else {  
  162.       
  163.       plural_memory[plural_space--] = (plural natural) (PP_iyproc+FREE_FLAG+1);
  164.     }
  165.   }
  166.    
  167.   if (!aok) return FAIL;
  168. DBG_EXIT(fprintf(dbg,"SUCCESS: plural_space=%u",plural_space));
  169.   return (natural) SUCCESS;
  170. }
  171.  
  172.  
  173. /*----------------------------------------------------------------------------*
  174.  * Function   : update_mgmt_data
  175.  *
  176.  * Parameters : int offset:    The slice of plural space to updat
  177.  *        int width:    The width of theallocated rectangle
  178.  *        int height:    The height of the allocated rectangle
  179.  *        int br_x:    X co-ord of bottom right corner of rectangle
  180.  *        int br_y:@    Y co-ord of bottom right corner of rectangle
  181.  *
  182.  * Description: The specified rectangle has just been allocated in the offset
  183.  *        slice of the plural space. The contents need to be set to NIL
  184.  *        and the management data updated where appropriate
  185.  *
  186.  * Result     : void
  187.  *---------------------------------------------------------------------------*/
  188.  
  189. #ifdef __STDC__
  190.  
  191. void update_mgmt_data( int offset, int width, int height, int br_x, int br_y )
  192.  
  193. #else
  194.  
  195. void update_mgmt_data( offset,  width,  height,  br_x,  br_y )
  196.  
  197. int offset;
  198. int width;
  199. int height;
  200. int br_x;
  201. int br_y;
  202.  
  203. #endif
  204.  
  205. {
  206.   plural natural mgmt_data;
  207.   plural natural bottom_edge;
  208. DBG_CALL("update_mgmt_data");
  209. DBG_ARGS(fprintf(dbg,"offset=%d, width=%d, height=%d, br_x=%d, br_y=%d",offset,width,height,br_x,br_y));
  210.  
  211.   bottom_edge = (mgmt_data=(plural_memory[offset] & (~FREE_FLAG))) >= height;
  212.  
  213.   if ((PP_ixproc > (br_x - width))  && (PP_ixproc <= br_x) &&
  214.       (PP_iyproc > (br_y - height)) && (PP_iyproc <= br_y))
  215.     
  216.     plural_memory[offset] = NIL;
  217.  
  218.   if ((PP_ixproc >= ((1 + br_x) - width))  && (PP_ixproc <= br_x) &&
  219.       (PP_iyproc > br_y) && bottom_edge) {
  220. DEBUG(DBG_PARG("PP_iyproc"," %d",PP_iyproc));
  221. DEBUG(DBG_PARG("mgmt_data"," %d",mgmt_data));    
  222.     if ((PP_iyproc + 1 - mgmt_data) < br_y) 
  223.       plural_memory[offset] = PP_iyproc - br_y + FREE_FLAG;
  224. DEBUG(DBG_PARG("new_data"," %d",plural_memory[offset]));
  225.   }
  226. }
  227.  
  228.  
  229. /*----------------------------------------------------------------------------*
  230.  * Function   : identify_rectangle
  231.  *
  232.  * Parameters : int offset:    The slice of plural space we are trying to
  233.  *                find a free rectangle in.
  234.  *        int width:    The desired width of the rectangle
  235.  *        int height:    The desired height of the rectangle
  236.  *        int *br_x:    To return the x co-ord of bottom right corner
  237.  *        int *br_y:    To return the y co-ord of bottom right corner
  238.  *
  239.  * Description: Attempts to find a free rectangle of the designated size in
  240.  *        the offset slice of the plural space, returning the 
  241.  *        co-ordinates of the bottom right corner in the two given
  242.  *        parameters is successful and updating teh management data
  243.  *        appropriately
  244.  *
  245.  * Result     : int : FAIL/SUCCESS
  246.  *---------------------------------------------------------------------------*/
  247.  
  248. #ifdef __STDC__
  249.  
  250. int identify_rectangle( natural offset, natural width, natural height
  251.             natural *br_x, natural *br_y )
  252.  
  253. #else
  254.  
  255. int identify_rectangle( offset, width, height, br_x, br_y )
  256.  
  257. natural offset;
  258. natural width;
  259. natural height;
  260. natural *br_x;
  261. natural *br_y;
  262.  
  263. #endif
  264.  
  265. {
  266.   natural br_iproc;
  267.   plural natural mgmt_data;
  268.   plural natural br_corner;
  269.   plural natural bottom_edge;
  270.   plural natural right_edge = FALSE;
  271.   plural char seg = ((PP_ixproc == (PP_nxproc - 1)) ? 1 : 0);
  272. DBG_CALL("identify_rectangle");
  273. DBG_ARGS(fprintf(dbg,"offset=%d, width=%d, height=%d, br_x=%x, br_y=%x", offset, width, height, br_x, br_y));
  274.  
  275.   mgmt_data = plural_memory[offset] & (~FREE_FLAG);
  276.  
  277.   bottom_edge = (mgmt_data >= height) && (plural_memory[offset] & FREE_FLAG);
  278.  
  279.   if (PP_ixproc < (PP_nxproc - 1))
  280.     seg = bottom_edge && PP_xnetE(1).(!bottom_edge);
  281.  
  282.   if (bottom_edge) {
  283.  
  284. DEBUG(DBG_PARG("(bottom_edge) iproc","%d ",iproc));
  285.     right_edge = scanAdd16u((plural natural) 1, seg) >= width;
  286.   }
  287.  
  288.   br_corner = bottom_edge && right_edge;
  289.   if (globalor(br_corner)) {
  290.  
  291.     if (br_corner) br_iproc = reduceMin16(PP_iproc);
  292.     *br_x = br_iproc % PP_nxproc;
  293.     *br_y = br_iproc / PP_nxproc;
  294.     update_mgmt_data(offset,width,height,*br_x,*br_y);
  295.  
  296. DBG_EXIT(fprintf(dbg,"SUCCESS: *br_x=%d, *br_y=%d", *br_x, *br_y));
  297.     return SUCCESS;
  298.   }
  299.  
  300.   return FAIL;
  301. }
  302.  
  303.  
  304. /*----------------------------------------------------------------------------*
  305.  * Function   : find_rectangle
  306.  *
  307.  * Parameters : int *offset:    To return the slice the rectangle is in
  308.  *        int width:    The desired width of the rectangle
  309.  *        int height:    The desired height of the rectangle
  310.  *        int *br_x:    To return teh x co-ord of bottom right corner
  311.  *        int *br_y:    To return the y co-ord of bottom right corner
  312.  *
  313.  * Description: Searches through the plural space, extending it if necessary,
  314.  *        for a free rectangle of width x heigth PEs. The coords
  315.  *        of the bottom right hand corner are returned in the two
  316.  *        given parameters.
  317.  *
  318.  * Result     : int:    FAIL/SUCCESS
  319.  *---------------------------------------------------------------------------*/
  320.  
  321. #ifdef __STDC__
  322.  
  323. natural find_rectangle( natural *offset, natural width, natural height, natural *br_x, natural *br_y )
  324.  
  325. #else
  326.  
  327. int find_rectangle( offset, width, height, br_x, br_y )
  328.  
  329. natural *offset;
  330. natural width;
  331. natural height;
  332. natural *br_x;
  333. natural *br_y;
  334.  
  335. #endif
  336.  
  337. {
  338. DBG_CALL("find_rectangle");
  339. DBG_ARGS(fprintf(dbg,"offset=%x, width=%d, height=%d, br_x=%x, br_y=%x",offset,width,height,br_x,br_y));
  340.  
  341.   *offset = TOP;
  342.   
  343.   while (*offset >= plural_space) {
  344.  
  345.     if ((*offset == plural_space) && (extend_plural_space() == FAIL)) {
  346.  
  347. DBG_FAIL(fprintf(dbg,"FAIL: Unable to extend plural space"));
  348.       return FAIL;
  349.     }
  350.  
  351.     if (identify_rectangle(*offset,width,height,br_x,br_y)) {
  352.       
  353. DBG_EXIT(fprintf(dbg,"SUCCESS: *offset=%d, *br_x=%d, *br_y=%d",*offset,*br_x,*br_y));
  354.       return SUCCESS;
  355.     }
  356.     --(*offset);
  357.   }
  358.  
  359. DBG_FAIL(fprintf(dbg,"FAIL: Never expected to get here"));
  360. }
  361.     
  362.  
  363. /*----------------------------------------------------------------------------*
  364.  * Function   : find_space
  365.  *
  366.  * Parameters : *offset:    To pass back the offset in local memory
  367.  *                the space is located at.
  368.  *        int width:    Width of rectangular pe set
  369.  *        int height:    Height of rectangular pe set
  370.  *        int br_x:    X co-ord of bottom right corner of pe set
  371.  *        int br_y:    Y co-ord of bottom right corner of pe set
  372.  *
  373.  * Description: searches for space in the plural space on the pes in
  374.  *        the rectangular region sepcified. Extends the plural
  375.  *        space if necessary, initilaises space to NIL and updates
  376.  *        the management data where appropriate.
  377.  *
  378.  * Result     : natural :    SUCCESS - located space
  379.  *                FAIL    - unable to locate sufficient space
  380.  *---------------------------------------------------------------------------*/
  381.  
  382. #ifdef __STDC__
  383.  
  384. int find_space( natural *offset, natural width, natural height, natural br_x, natural br_y )
  385.  
  386. #else
  387.  
  388. int find_space( offset, width, height, br_x, br_y )
  389.  
  390. natural *offset;
  391. natural width;
  392. natural height;
  393. natural br_x;
  394. natural br_y;
  395.  
  396. #endif
  397.  
  398. {
  399.   int got_some = FALSE;
  400. DBG_CALL("find_space");
  401. DBG_ARGS(fprintf(dbg,"offset=%x,width=%d,height=%d,br_x=%d,br_y=%d",offset,width,height,br_x,br_y));
  402.  
  403.   *offset = 1+stack_base;          /* Memory offset currently being examined */
  404.  
  405.   while ((*offset >= plural_space) && !got_some) { 
  406.     
  407.     (*offset)--;
  408. DEBUG(fprintf(dbg,"*offset=%d",*offset));
  409.     if ((*offset == plural_space) && (extend_plural_space() == FAIL)) {
  410.  
  411. DBG_FAIL(fprintf(dbg,"FAIL: Unable to extend space"));
  412.       return FAIL;    
  413.     }
  414.  
  415.     if ((PP_ixproc >= ((1 + br_x) - width))  && (PP_ixproc <= br_x) &&
  416.     (PP_iyproc >= ((1 + br_y) - height)) && (PP_iyproc <= br_y)) {
  417.  
  418. DEBUG(DBG_PARG("iproc","%d ",iproc));
  419. DEBUG(DBG_PARG("mgmt_data","%d ",plural_memory[*offset]));
  420.  
  421.       got_some = !globalor(!(plural_memory[*offset]&FREE_FLAG));
  422. DEBUG(fprintf(dbg,"got_some=%d",got_some));
  423.     }
  424.   }
  425.   
  426.   update_mgmt_data(*offset,width,height,br_x,br_y);
  427. DBG_EXIT(fprintf(dbg,"SUCCESS: *offset=%d",*offset));
  428.   return SUCCESS;
  429. }
  430.  
  431. /*----------------------------------------------------------------------------*
  432.  * Function   : alloc_plural
  433.  *
  434.  * Parameters : object MPP_conform:    MP_Plural object new plural should
  435.  *                    conform to. Empty if creating new
  436.  *                    context
  437.  *
  438.  * Description: Either creates a new context, or creates a new plural in the
  439.  *        given context. If a new context is eing created its description
  440.  *        is passed back in MPC_conform and its size is specified by 
  441. v *        length. 
  442.  *        A new plural is characterised by its offset into the plural
  443.  *        space and this is returned.
  444.  *
  445.  * Result     : natural:    Offset into plural space
  446.  *                0 if unable to allocate
  447.  *---------------------------------------------------------------------------*/
  448.  
  449. #ifdef __STDC__
  450.  
  451. natural alloc_plural( object MPC_conform )
  452.  
  453. #else
  454.  
  455. natural alloc_plural( MPC_conform )
  456.  
  457. object MPC_conform;
  458.  
  459. #endif
  460.  
  461. {
  462.   natural offset;
  463. DBG_CALL("alloc_plural");
  464. DBG_ARGS(fprintf(dbg,"MPC_conform=%x",MPC_conform));
  465.  
  466.    if (OA_offset(MPC_conform) == 0) { /* Fresh context object */
  467.  
  468.      if (find_rectangle(&OA_offset(MPC_conform), OA_width(MPC_conform),
  469.             OA_height(MPC_conform), &OA_br_x(MPC_conform),
  470.             &OA_br_y(MPC_conform)) == FAIL) {
  471.  
  472. DBG_FAIL(fprintf(dbg,"FAIL: Unable to allocate plural space"));
  473.        return FAIL;
  474.      }
  475. DBG_EXIT(fprintf(dbg,"SUCCESS: offset=%u, br_x=%u, br_y=%u",OA_offset(MPC_conform),OA_br_x(MPC_conform),OA_br_y(MPC_conform)));
  476.      return SUCCESS;
  477.    } 
  478.   if (find_space(&offset, OA_width(MPC_conform), OA_height(MPC_conform),
  479.          OA_br_x(MPC_conform), OA_br_y(MPC_conform)) == FAIL) {
  480.     
  481. DBG_FAIL(fprintf(dbg,"FAIL: Unable to allocate plural space"));
  482.     return FAIL;
  483.   }
  484.    
  485. DBG_EXIT(fprintf(dbg,"%u",offset));
  486.   return offset;
  487. }
  488.  
  489. /*----------------------------------------------------------------------------*
  490.  * Function   : scanaddy
  491.  *
  492.  * Parameters : plural natural val:    plural of 16-bit Nos to scan
  493.  *        plural char segment:    segmentation (in y-axis)
  494.  *
  495.  * Description: Performs the same task as scanAdd16 but the operation is
  496.  *          done indepedently in each y column.
  497.  *
  498.  * Result     : plural natural: the result.
  499.  *---------------------------------------------------------------------------*/
  500.  
  501. #ifdef __STDC__
  502.  
  503. plural natural scanaddy( plural natural val, plural char segment )
  504.  
  505. #else
  506.  
  507. plural natural scanaddy( val, segment )
  508.  
  509. plural natural val;
  510. plural char segment;
  511.  
  512. #endif
  513.              
  514. {
  515.   plural natural sum = val;
  516.   plural natural tmp;
  517.   int step = 1;
  518.   int i;
  519.  
  520.   while (step < PP_nyproc) {
  521.  
  522.     tmp=0;
  523.     if (!segment) PP_xnetS(step).tmp = sum;
  524.     if (!globalor(!segment)) break;
  525.     segment = segment || PP_xnetS(step).segment;
  526.     step = step*2;
  527.  
  528.   }
  529.  
  530.   return sum;
  531. }
  532.  
  533.  
  534.  
  535.  
  536. /*----------------------------------------------------------------------------*
  537.  * Function   : mp_free_plurals
  538.  *
  539.  * Parameters : char *fe_address:    THe address of the beginning of a 
  540.  *                    list on the host of active plurals
  541.  *         int  no_of_plurals:    The number of entries in th list.
  542.  *
  543.  * Description: Pages in the front end list of active plurals and marks them as
  544.  *        being active. Then scans through the plural space, making
  545.  *        the management data correct and clearing the active flags for
  546.  *        the next pass. Modifications to support GC protect stack
  547.  *        the free plurals pass is only applied between TOP and
  548.  *        stackbase if stackbase not equal to TOP.
  549.  *
  550.  * Result     : int:    SUCCESS - everything was groovy
  551.  *            FAIL    - something strange and ungroovy happened
  552.  *---------------------------------------------------------------------------*/
  553.  
  554. #ifdef __STDC__
  555.  
  556. visible int mp_free_plurals( char *fe_address, int no_of_plurals )
  557.  
  558. #else
  559.  
  560. visible int mp_free_plurals( fe_address, no_of_plurals )
  561.  
  562. char *fe_address;
  563. int no_of_plurals;
  564.  
  565. #endif
  566.  
  567. {
  568.   int ps_offset;        /* Offset into the plural space       */
  569.   int page_no = 0;        /* Current fe plural list page number */
  570.   object MPC_curr, MPC_next;    /* Current, next MasPar Context object*/
  571.   object *P_MPC_curr;           /* Pointer to current MasPar Context  */
  572.   plural char segments;         /* for scan operations                */
  573.   plural natural potential_PE;
  574.   plural natural tmp;
  575.   natural new_plural_space = TOP;
  576.   natural Bottom = (stack_base == TOP) ? plural_space : stack_base;
  577.   int i;
  578.   natural *page = (natural *) acu_scratch;  /* acu_scratch in 16-bit words */
  579.   int page_offset;
  580.  
  581. DBG_CALL("free_plurals");
  582. DBG_ARGS(fprintf(dbg,"fe_address=%x, no_of_plurals=%d, Bottom=", fe_address, no_of_plurals,Bottom);if (stack_base==TOP) fprintf(dbg,"plural_space(=%d)",plural_space);else fprintf(dbg,"stack_base(=%d)",stack_base));
  583.  
  584. DO_DEBUG(fprintf(stderr,"Bottom=%s(=%d)",((stack_base==TOP)?"plural_space":"stack_base"),((stack_base==TOP)?plural_space:stack_base)));
  585.  
  586.   /*  Step through entire plural space and mark as free */
  587.  
  588.   for (ps_offset = TOP; ps_offset > Bottom; ps_offset--) {
  589.  
  590.     tmp = plural_memory[ps_offset];
  591.     tmp = tmp | FREE_FLAG;
  592.     plural_memory[ps_offset] = tmp;
  593.   }
  594.  
  595.   /*  Step through chain of MasPar Context objects and mark as being free */
  596.  
  597.   for (MPC_curr=MPC_chain; MPC_curr != NULL; MPC_curr = MPC_next) {
  598.     
  599.     MPC_next = OA_next(MPC_curr);
  600.     OF_free(MPC_curr);
  601.   }
  602.   
  603.   while (no_of_plurals > 0) {
  604.  
  605.     /* Page in plural list from host */
  606.  
  607.     if (copyIn(fe_address, acu_scratch, SCRATCH_MEMORY_SIZE) != 0) {
  608.  
  609.       mp_error = MP_COPY_IN_FAILED;
  610. DBG_FAIL(fprintf(dbg,"FAIL: Error loading page %d",page_no));
  611.       return FAIL;
  612.     }
  613.  
  614.     /* update page orientated data */
  615.  
  616.     fe_address = fe_address + SCRATCH_MEMORY_SIZE;
  617.     no_of_plurals = no_of_plurals - (SCRATCH_MEMORY_SIZE/(2*sizeof(natural)));
  618.     page_offset = 0;
  619.     page_no++;
  620.  
  621.     /*  for each offset,context_address pair in the page, mark the given
  622.      *  area in the plural space as being not free
  623.      */
  624.  
  625.     for (i=0; i < (SCRATCH_MEMORY_SIZE/(2*sizeof(natural)) +
  626.               ((no_of_plurals < 0) ? no_of_plurals : 0)); i++) {
  627.  
  628.       /* first 16-bit number is a context address, get hold of the context
  629.        * and mark it as being not free. The second 16-bits are the offset */
  630.  
  631.       MPC_curr  = (object) *(page + page_offset);
  632.       OM_not_free(MPC_curr);
  633.     
  634.       ps_offset = *(page + page_offset + 1);
  635.       new_plural_space = (ps_offset < new_plural_space) ? ps_offset :
  636.     new_plural_space;
  637.  
  638.       OM_with_context(MPC_curr) {
  639. /*      if ((OA_start(MPC_curr) <= PP_iproc) &&
  640.       (PP_iproc < (OA_start(MPC_curr) + OA_length(MPC_curr)))) {
  641. */
  642.     plural_memory[ps_offset] = plural_memory[ps_offset] & (~FREE_FLAG);
  643.       }
  644.  
  645.       page_offset += 2;                     /* Next Context,Offset pair */
  646.     }
  647.   }
  648.  
  649.   /*  Now we need to go through all the MPC_contexts, free those which are
  650.    *  "free" and mark all the plural space used by each context for it's
  651.    *  context stack */
  652.  
  653.   for (P_MPC_curr = &MPC_chain; *P_MPC_curr != NULL; ) {
  654.  
  655.     MPC_curr = *P_MPC_curr;
  656.     if (OM_freep(MPC_curr)) {
  657.  
  658.       OM_not_free(MPC_curr); /* To manipulate cannot be free! */
  659.       *P_MPC_curr = OA_next(MPC_curr);
  660.       OF_destroy(MPC_curr);
  661.     }
  662.     else {
  663.  
  664.       P_MPC_curr = &(OA_next(MPC_curr));
  665.       OM_with_context(MPC_curr) {
  666. /*      if ((OA_start(MPC_curr) <= PP_iproc) &&
  667.       (PP_iproc < (OA_start(MPC_curr) + OA_length(MPC_curr)))) {
  668. */
  669.     new_plural_space = (OA_offset(MPC_curr) < new_plural_space) 
  670.       ? OA_offset(MPC_curr): new_plural_space;
  671.     plural_memory[OA_offset(MPC_curr)] =
  672.       plural_memory[OA_offset(MPC_curr)] & (~FREE_FLAG);
  673.       }
  674.     }
  675.   }
  676.   
  677.   /*  Now need to generate correct management data, each free slot, */
  678.   /*  needs to have the number of contiguous pes are free above it  */
  679.  
  680.   for (ps_offset = TOP; ps_offset > Bottom; ps_offset--) {
  681.  
  682.     /*  Need to identify the "bottom" most PE of each FREE segment, my
  683.      *  scan function uses this information to partition its operation
  684.      *  into independent sets of processors
  685.      */
  686.     
  687.     /* All PEs who are free and their down neighbour is not free */
  688.  
  689.     potential_PE = (plural_memory[ps_offset] & FREE_FLAG) == FREE_FLAG;
  690.     segments = potential_PE && PP_xnetS(1).(!potential_PE);
  691.  
  692.     /* The bottom row is a special case as we cam't poll their down */
  693.     /* neighbours */
  694.  
  695.     if (PP_iyproc == (PP_nyproc - 1)) segments = 0;
  696.  
  697.     PP_on_set() {
  698.  
  699.       if (potential_PE) {
  700.       
  701.     tmp = scanaddy((plural natural) 1,segments);
  702.     plural_memory[ps_offset] = tmp | FREE_FLAG;
  703.       }
  704.     }
  705.   }
  706.   
  707.   /*  If there isn't a GC Protect stack at the moment - probably unlikely
  708.    *  but no harm in hoping, then we can take advantage of any "shrink"
  709.    *  in the number of handles in theglobal environment
  710.    */
  711.  
  712.   if (stack_base == TOP) {
  713.  
  714.     fprintf(stderr,"plural_space changed from %d to %d\n",plural_space,new_plural_space-1);
  715.     plural_space = new_plural_space - 1;
  716.   }
  717. /*  mp_gc();*/
  718.  
  719. DBG_EXIT(fprintf(dbg,"SUCCESS"));
  720.   return SUCCESS;
  721. }
  722.                
  723.  
  724.